# -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv
from openerp.tools.translate import _
import csv
from subprocess import call
from datetime import datetime, timedelta

class hr_attendance(osv.osv):
    _inherit = "hr.attendance"

    _columns = {
        'mdb_logid': fields.integer('Logid at MDB Files'),
    }

    def hr_attendance_mdb_files_link(self, cr, uid, ids, context=None):
        #check Data Validation
        user_obj = self.pool.get('res.users')
        attendance_obj = self.pool.get('hr.attendance')
        employee_obj = self.pool.get('hr.employee')
        mdb_exception_obj = self.pool.get('hr.attendance.mdb.exception')
        mdb_exception_lines_obj = self.pool.get('mdb.exception.lines')
        company = user_obj.browse(cr, uid, uid, context=None).company_id
        file_path = company.url or ''
        file_name = company.datas_fname or ''
        csv_path = company.url2 or ''
#
        mdb_path=file_path + file_name
        try:
            f = open(mdb_path, 'r')
            s = f.readline()
        except IOError as e:
            raise osv.except_osv(_('Error!'),_("I/O error({0}): {1}".format(e.errno, e.strerror)))
        csv_path=csv_path + 'output.csv'
        conversion_string="mdb-export %s CHECKINOUT | tail -n +2 | cut -d, -f1,2,3,4 | tr / - >%s"%(mdb_path,csv_path)
        call(conversion_string,shell=True)
        p = open(csv_path,'r')

        re = csv.reader(p,delimiter=',',quoting=csv.QUOTE_NONE)
        val = []
        for r in re:
            mdb_logid= int(r[0])
            user_id= int(r[1].replace('\"',''))
            checktime=r[2].replace('\"','')
            checktype=r[3].replace('\"','')
            if checktype == "I":
                action = "sign_in"
            elif checktype == "O":
                action = "sign_out"
            else:
                action = "error"
            val.append({
               'mdb_logid' : mdb_logid,
               'user_id' : user_id,
               'checktime' : checktime,
               'checktype' : action,
               'typestring' : checktype,
               })
        val = val and sorted(val, key=lambda val_res: val_res['checktime']) or []
        val = val and sorted(val, key=lambda val_res: val_res['user_id']) or []
        mdbuser_id = False
        error_uid = False
        error_user_id = False
        error_logid = False
        exception_id = False
        for data in val:
            if attendance_obj.search(cr, uid, [('mdb_logid', '=', data['mdb_logid'])]):
                continue
            if not mdbuser_id:
                mdbuser_id = data['user_id']
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['checktype'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
            elif data['user_id'] == error_uid:
                if not exception_id:
                    exception_id =  mdb_exception_obj.create(cr, uid, {
                                        'name': datetime.now(),
                                        })
                mdb_exception_lines_obj.create(cr, uid, {
                                        'parent_id': exception_id,
                                        'name': "Fix no User Id '%s' found for Mdb Files at employee before continue to mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                        })
                continue
            elif data['user_id'] == error_user_id:
                if not exception_id:
                    exception_id =  mdb_exception_obj.create(cr, uid, {
                                        'name': datetime.now(),
                                        })
                mdb_exception_lines_obj.create(cr, uid, {
                                        'parent_id': exception_id,
                                        'name': "Fix User Id '%s', mdb_login_id '%s' error first before continue to mdb_logid  '%s'"%(error_user_id,error_logid,data['mdb_logid'])
                                        })
                continue
            elif data['user_id'] == mdbuser_id:
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_log_id '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['checktype'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
            else:
                error_uid = False
                error_user_id = False
                error_logid = False
                mdbuser_id = data['user_id']
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name':  "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
        return True

    def _hr_attendance_mdb_files_link(self, cr, uid, context=None):
        #check Data Validation
        user_obj = self.pool.get('res.users')
        attendance_obj = self.pool.get('hr.attendance')
        employee_obj = self.pool.get('hr.employee')
        mdb_exception_obj = self.pool.get('hr.attendance.mdb.exception')
        mdb_exception_lines_obj = self.pool.get('mdb.exception.lines')
        company = user_obj.browse(cr, uid, uid, context=None).company_id
        file_path = company.url or ''
        file_name = company.datas_fname or ''
        csv_path = company.url2 or ''
#
        mdb_path=file_path + file_name
        try:
            f = open(mdb_path, 'r')
            s = f.readline()
        except IOError as e:
            raise osv.except_osv(_('Error!'),_("I/O error({0}): {1}".format(e.errno, e.strerror)))
        csv_path=csv_path + 'output.csv'
        conversion_string="mdb-export %s CHECKINOUT | tail -n +2 | cut -d, -f1,2,3,4 | tr / - >%s"%(mdb_path,csv_path)
        call(conversion_string,shell=True)
        p = open(csv_path,'r')

        re = csv.reader(p,delimiter=',',quoting=csv.QUOTE_NONE)
        val = []
        for r in re:
            mdb_logid= int(r[0])
            user_id= int(r[1].replace('\"',''))
            checktime=r[2].replace('\"','')
            checktype=r[3].replace('\"','')
            if checktype == "I":
                action = "sign_in"
            elif checktype == "O":
                action = "sign_out"
            else:
                action = "error"
            val.append({
               'mdb_logid' : mdb_logid,
               'user_id' : user_id,
               'checktime' : checktime,
               'checktype' : action,
               'typestring' : checktype,
               })
        val = val and sorted(val, key=lambda val_res: val_res['checktime']) or []
        val = val and sorted(val, key=lambda val_res: val_res['user_id']) or []
        mdbuser_id = False
        error_uid = False
        error_user_id = False
        error_logid = False
        exception_id = False
        for data in val:
            if attendance_obj.search(cr, uid, [('mdb_logid', '=', data['mdb_logid'])]):
                continue
            if not mdbuser_id:
                mdbuser_id = data['user_id']
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['checktype'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
            elif data['user_id'] == error_uid:
                if not exception_id:
                    exception_id =  mdb_exception_obj.create(cr, uid, {
                                        'name': datetime.now(),
                                        })
                mdb_exception_lines_obj.create(cr, uid, {
                                        'parent_id': exception_id,
                                        'name': "Fix no User Id '%s' found for Mdb Files at employee before continue to mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                        })
                continue
            elif data['user_id'] == error_user_id:
                if not exception_id:
                    exception_id =  mdb_exception_obj.create(cr, uid, {
                                        'name': datetime.now(),
                                        })
                mdb_exception_lines_obj.create(cr, uid, {
                                        'parent_id': exception_id,
                                        'name': "Fix User Id '%s', mdb_login_id '%s' error first before continue to mdb_logid  '%s'"%(error_user_id,error_logid,data['mdb_logid'])
                                        })
                continue
            elif data['user_id'] == mdbuser_id:
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_log_id '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['checktype'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
            else:
                error_uid = False
                error_user_id = False
                error_logid = False
                mdbuser_id = data['user_id']
                employee_ids = employee_obj.search(cr, uid, [('mdb_user_id', '=', data['user_id'])])
                if not employee_ids:
                    error_uid = mdbuser_id
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "User Id '%s' for Mdb Files not Found at Employee for mdb_logid '%s'"%(error_uid,data['mdb_logid'])
                                            })
                    continue
                employee_id = employee_ids[0]
                #check error Data type
                checktype = data['checktype']
                if checktype == 'error':
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name': "error for type, the type not in ('I,'O') but '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                #check previous type
                check_previous_type = False
                attendance_ids = attendance_obj.search(cr, uid, [('employee_id', '=', employee_id),('name','<=',data['checktime'])], order="name Desc", limit=1)
                if attendance_ids:
                    check_previous_type = attendance_obj.browse(cr, uid, attendance_ids[0], context=None).action
                if check_previous_type and check_previous_type == checktype:
                    error_user_id = mdbuser_id
                    error_logid = data['mdb_logid']
                    if not exception_id:
                        exception_id =  mdb_exception_obj.create(cr, uid, {
                                            'name': datetime.now(),
                                            })
                    mdb_exception_lines_obj.create(cr, uid, {
                                            'parent_id': exception_id,
                                            'name':  "error for type, the previous type is same with the type. '%s', user_id '%s', mdb_logid '%s'"%(data['typestring'],error_user_id,error_logid)
                                            })
                    continue
                attendance_obj.create(cr, uid, {
                    'name': data['checktime'],
                    'employee_id': employee_id,
                    'action': checktype,
                    'mdb_logid': data['mdb_logid'],
                    })
        return True
hr_attendance()

class hr_attendance_mdb_exception(osv.osv):
    _name = "hr.attendance.mdb.exception"
    _description = "Attendance Import Mdb Files Exception"

    _columns = {
        'name': fields.datetime('Date', required=True, select=1),
        'line_id': fields.one2many('mdb.exception.lines', 'parent_id', 'Error Lines'),
    }

hr_attendance_mdb_exception()

class mdb_exception_lines(osv.osv):
    _name = "mdb.exception.lines"
    _description = 'Exception Lines'

    _columns = {
        'parent_id': fields.many2one('hr.attendance.mdb.exception', "Header", required=True, select=True, ondelete="cascade"),
        'name': fields.char('Error Description', required=True, help='Error Description.'),
    }

hr_attendance_mdb_exception()
    
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
